package com.zeyu.soc.log.spi.impl;

import java.io.IOException;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

import com.zeyu.soc.log.spi.TransformDescriptor;
import com.zeyu.soc.log.spi.TransformHandler;
import com.zeyu.soc.log.tools.MacroUtils;
import com.zeyu.soc.log.utils.ExceptionUtils;

/**
 * 处理行号
 */
public class LineLogTransformHandler implements TransformHandler {

	// ================================================================
	// Constants
	// ================================================================

	// ================================================================
	// Fields
	// ================================================================

	// ================================================================
	// Constructors
	// ================================================================

	// ================================================================
	// Methods from/for super Interfaces or SuperClass
	// ================================================================

	@Override
	public boolean canHandler(TransformDescriptor injectDescriptor) {
		if (null == injectDescriptor) {
			return false;
		}
		return LineLogTransformDescriptor.class.isAssignableFrom(injectDescriptor.getClass());
	}

	@Override
	public byte[] transform(TransformDescriptor injectDescriptor) {
		LineLogTransformDescriptor descriptor = (LineLogTransformDescriptor) injectDescriptor;
		try {
			// 通过包名获取类文件
			CtClass cc = ClassPool.getDefault().get(descriptor.getNeedInjectClassName());
			cc.defrost();
			// 获得指定方法名的方法
			CtMethod m = cc.getDeclaredMethod(descriptor.getMethodName());
			// 插入预输入的代码
			m.insertAt(Integer.valueOf(descriptor.getLineNum()),
					MacroUtils.safeInsertTemplate(descriptor.getLineCode() + ";"));
			return cc.toBytecode();
		} catch (NotFoundException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
		} catch (CannotCompileException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
		} catch (IOException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
		}
		return null;

	}

	// ================================================================
	// Public or Protected Methods
	// ================================================================

	// ================================================================
	// Getter & Setter
	// ================================================================

	// ================================================================
	// Private Methods
	// ================================================================

	// ================================================================
	// Inner or Anonymous Class
	// ================================================================

	// ================================================================
	// Test Methods
	// ================================================================
}
